package org.fastsyncer.server.jetty;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.ResourceBundle;

import org.apache.commons.configuration.PropertiesConfiguration;
import org.fastsyncer.common.constant.CommonConstant;
import org.fastsyncer.common.util.ApplicationUtil;
import org.fastsyncer.common.util.ZipUtil;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.webapp.WebAppClassLoader;
import org.mortbay.jetty.webapp.WebAppContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class JettyServer implements Runnable {

    private static Logger logger = LoggerFactory.getLogger(JettyServer.class);

    private static Server server;

    static {
        // 加载默认配置文件（application.properties）
        ResourceBundle pro = ResourceBundle.getBundle("application");
        Enumeration<String> keys = pro.getKeys();
        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            String value = pro.getString(key);
            ApplicationUtil.setKey(key, value);
        }

        // 这里会读取fastsyncer-common\target\classes路径下的编译生成文件,如果Project>>clean 那么文件会重新从src读取最新的配置
        URL properties = JettyServer.class.getClassLoader().getResource("application.properties");
        // 保存配置文件地址
        if(null!=properties){
            ApplicationUtil.setKey(CommonConstant.CONFIG_PATH_APPLICATION_PROPERTIES, properties.getPath());
        }
        ApplicationUtil.setKey(JettyServerEnum.PORT.getKey(), JettyServerEnum.PORT.getValue());
        ApplicationUtil.setKey(JettyServerEnum.CONTEXT.getKey(), JettyServerEnum.CONTEXT.getValue());
        ApplicationUtil.setKey(JettyServerEnum.WEB_PATH.getKey(), JettyServerEnum.WEB_PATH.getValue());
        ApplicationUtil.setKey(JettyServerEnum.ROOT.getKey(), JettyServerEnum.ROOT.getValue());
        ApplicationUtil.setKey(JettyServerEnum.ROOT_DESCRIPTOR.getKey(), JettyServerEnum.ROOT_DESCRIPTOR.getValue());
    }

    private JettyServer(String[] args) throws IOException {
        this.load(args);

        // 默认
        String _ip = ApplicationUtil.getKey(CommonConstant.SERVER_IP);
        String _port = ApplicationUtil.getKey(JettyServerEnum.PORT.getKey());
        String _context = ApplicationUtil.getKey(JettyServerEnum.CONTEXT.getKey());
        String serviceAddr = "http://" + _ip + ":" + _port + _context;
        // 本地服务地址
        ApplicationUtil.setKey(CommonConstant.SERVER_SERVICE_ADDRESS, serviceAddr);
        String auth = _context.endsWith("/") ? serviceAddr + "authenticate" : serviceAddr + "/authenticate";
        ApplicationUtil.setKey(CommonConstant.SERVER_SERVICE_ADDRESS_AUTHENTICATE, auth);
        logger.info("ip:" + ApplicationUtil.getKey(CommonConstant.SERVER_IP));
        logger.info("args:" + Arrays.toString(args));
        logger.info("root:" + ApplicationUtil.getKey(JettyServerEnum.ROOT.getKey()));
        logger.info("root.descriptor:" + ApplicationUtil.getKey(JettyServerEnum.ROOT_DESCRIPTOR.getKey()));
        logger.info("service.address:" + serviceAddr);
    }

    /**
     * 初始化配置信息
     * 
     * @param args
     */
    private void load(String[] args) {
        try {
            if (args != null && args.length > 0) {
                // 上下文路径：/opt/fastsyncer-server-X.X.X-Release
                String currentPath = args[0];

                // UI路径：/opt/fastsyncer-server-X.X.X-Release/ui
                String uiDir = currentPath + File.separatorChar + "ui";
                // Zip包：/opt/fastsyncer-server-X.X.X-Release/ui/WEB-INF.zip
                String zipDir = uiDir + File.separatorChar + "WEB-INF.zip";
                // 解压后：/opt/fastsyncer-server-X.X.X-Release/ui/WEB-INF/...
                ZipUtil.unZip(zipDir, uiDir);

                // 1.获取配置文件：/opt/fastsyncer-server-X.X.X-Release/ui/conf/boot/application.properties
                String proPath = currentPath + "/conf/boot/application.properties";
                PropertiesConfiguration pro = new PropertiesConfiguration(proPath);
                Iterator<String> keys = pro.getKeys();
                while (keys.hasNext()) {
                    String key = keys.next();
                    // 覆盖写入
                    ApplicationUtil.setKey(key, pro.getString(key));
                }
                // 保存配置文件地址
                ApplicationUtil.setKey(CommonConstant.CONFIG_PATH_APPLICATION_PROPERTIES, proPath);
                // 替换web上下文配置
                ApplicationUtil.setKey(JettyServerEnum.ROOT.getKey(), JettyServerEnum.DEF_ROOT.getValue());
                ApplicationUtil.setKey(JettyServerEnum.ROOT_DESCRIPTOR.getKey(), JettyServerEnum.DEF_ROOT_DESC.getValue());
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 快速重新启动application，重载classes
     */
    private void reloadContext(Server server) throws Exception {
        WebAppContext context = (WebAppContext) server.getHandler();
        context.stop();
        // 设置上下文路径
        context.setContextPath(ApplicationUtil.getKey(JettyServerEnum.CONTEXT.getKey()));
        // 设置Web内容上下文路径
        context.setResourceBase(ApplicationUtil.getKey(JettyServerEnum.ROOT.getKey()));
        // 设置描述符位置
        context.setDescriptor(ApplicationUtil.getKey(JettyServerEnum.ROOT_DESCRIPTOR.getKey()));
        // 设置当前运行上下文
        context.setClassLoader(Thread.currentThread().getContextClassLoader());
        // 设置优先级
        context.setParentLoaderPriority(true);
        WebAppClassLoader classLoader = new WebAppClassLoader(context);
        context.setClassLoader(classLoader);
        context.start();
    }

    public static void main(String[] args) throws Exception {
        // 启用web服务
        JettyServer jettyServer = new JettyServer(args);
        Thread thread = new Thread(jettyServer, "server");
        thread.setDaemon(true);
        thread.start();
        while (true) {
            try {
                Thread.sleep(30000);
            } catch (Exception e) {
            }
        }
    }

    @Override
    public void run() {
        try {
            // 服务器的监听端口
            server = new Server(Integer.parseInt(ApplicationUtil.getKey(JettyServerEnum.PORT.getKey())));
            // 创建一个新的上下文
            WebAppContext context = new WebAppContext();
            server.setHandler(context);

            this.reloadContext(server);
            server.start();

            // 打印帮助信息
            String serviceAddr = ApplicationUtil.getKey(CommonConstant.SERVER_SERVICE_ADDRESS);
            logger.info("Start successfully! " + serviceAddr);

        } catch (Exception e) {
            logger.error(e.getMessage(), e.getClass(), e.getCause());
        }
    }

}